package com.excilys.capicsoubank.controllers;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.excilys.capicsoubank.entities.Account;
import com.excilys.capicsoubank.entities.TransactionType;

/**
 * Contrôle l'affichage de la page de détail d'un compte.
 * 
 * @author Nicolas Poirier
 */
@Controller
@RequestMapping("/account")
public class AccountController extends PaginationController {
	private static final Logger LOGGER = LoggerFactory
			.getLogger(HomeController.class);

	/**
	 * Contrôleur appelé pour l'adresse /account/accountId pour afficher le
	 * détail du compte accountId pour le mois courant.
	 * 
	 * @param accountId
	 *            l'identifiant du compte à afficher
	 * @return La vue accounts.jsp
	 */
	@RequestMapping("/{accountId}")
	public String accountById(@PathVariable("accountId") int accountId) {
		DateTime now = DateTime.now();
		return "redirect:/account/" + accountId + "/" + now.year().get() + "/"
				+ now.monthOfYear().get();
	}

	/**
	 * Contrôleur appelé pour l'adresse /account/accountId/year/month pour
	 * afficher le détail du compte accountId pour le mois demandé.
	 * 
	 * @param accountId
	 *            l'identifiant du compte à afficher
	 * @param year
	 *            l'année à afficher
	 * @param month
	 *            le mois à afficher
	 * @return La vue accounts.jsp
	 */
	@RequestMapping("/{accountId}/{year}/{month}")
	public String accountByIdAndMonth(@PathVariable("accountId") int accountId,
			@PathVariable("year") int year, @PathVariable("month") int month) {

		Object[] params = { accountId, year, month };
		LOGGER.debug("/account/{}/{}/{}", params);

		return "redirect:/account/" + accountId + "/" + year + "/" + month
				+ "/1";
	}

	/**
	 * Contrôleur appelé pour l'adresse /account/accountId/year/month/page pour
	 * afficher le détail du compte accountId pour le mois demandé et la page
	 * demandée.
	 * 
	 * @param model
	 *            le modèle
	 * @param redirectAttributes
	 *            le modèle utilisé pour la redirection
	 * @param accountId
	 *            l'identifiant du compte à afficher
	 * @param year
	 *            l'année à afficher
	 * @param month
	 *            le mois à afficher
	 * @param page
	 *            la page à afficher
	 * @return La vue accounts.jsp
	 */
	@RequestMapping("/{accountId}/{year}/{month}/{page}")
	public String accountByIdAndMonthAndPage(Model model,
			RedirectAttributes redirectAttributes,
			@PathVariable("accountId") int accountId,
			@PathVariable("year") int year, @PathVariable("month") int month,
			@PathVariable("page") int page) {

		Object[] params = { accountId, year, month, page };
		LOGGER.debug("/account/{}/{}/{}/{}", params);

		DateTime now = DateTime.now();
		int currentYear = now.year().get();
		int currentMonth = now.monthOfYear().get();

		paginationController(model, accountId, year, month, page,
				TransactionType.TRANSFER);

		model.addAttribute("creditCardOperationsSum", transactionService
				.getSumCardTransactionsByYearByMonth(accountId, year, month));

		// Trouve le premier jour du mois à afficher et le dernier jour
		// du mois
		DateTime firstDateSelectedMonth = getFirstDayOfMonth(year, month);
		DateTime lastDateSelectedMonth;

		// Pour le mois courant, il ne faut pas aller plus loin que la
		// date actuelle
		if (currentMonth != month || currentYear != year)
			lastDateSelectedMonth = getLastDayOfMonth(year, month);
		else
			lastDateSelectedMonth = now;

		model.addAttribute("lastDateSelectedMonth", lastDateSelectedMonth);
		model.addAttribute("firstDateSelectedMonth", firstDateSelectedMonth);

		model.addAttribute("lastBalanceSelectedMonth", accountService
				.getAccountBalanceAtSpecificDate(accountId,
						lastDateSelectedMonth));
		model.addAttribute("firstBalanceSelectedMonth", accountService
				.getAccountBalanceAtSpecificDate(accountId,
						firstDateSelectedMonth));

		return Template.page("accounts", "account", model,
				Account.class.cast(model.asMap().get("account")).getLabel());
	}

	/**
	 * Contrôleur appelé pour l'adresse /account/accountId/card pour afficher le
	 * détail des opérations carte du compte accountId pour le mois courant.
	 * 
	 * @param accountId
	 *            l'identifiant du compte à afficher
	 * @return La vue accounts.jsp
	 */
	@RequestMapping("/{accountId}/card")
	public String cardTransactionByAccountId(
			@PathVariable("accountId") int accountId) {

		LOGGER.debug("/account/{}/card", accountId);

		DateTime now = DateTime.now();

		return "redirect:/account/" + accountId + "/card/" + now.year().get()
				+ "/" + now.monthOfYear().get();
	}

	/**
	 * Contrôleur appelé pour l'adresse /account/accountId/card/month pour
	 * afficher le détail des opérations CB du compte accountId pour le mois
	 * demandé.
	 * 
	 * @param accountId
	 *            l'identifiant du compte à afficher
	 * @param year
	 *            l'année à afficher
	 * @param month
	 *            le mois à afficher
	 * @return La vue card.jsp
	 */
	@RequestMapping("/{accountId}/card/{year}/{month}")
	public String cardTransactionsByAccountIdAndMonth(
			@PathVariable("accountId") int accountId,
			@PathVariable("year") int year, @PathVariable("month") int month) {

		Object[] params = { accountId, year, month };
		LOGGER.debug("/account/{}/card/{}/{}", params);

		return "redirect:/account/" + accountId + "/card/" + year + "/" + month
				+ "/1";
	}

	/**
	 * Contrôleur appelé pour l'adresse /account/accountId/card/month pour
	 * afficher le détail des opérations CB du compte accountId pour le mois
	 * demandé.
	 * 
	 * @param model
	 *            le modèle
	 * @param redirectAttributes
	 *            le modèle utilisé pour la redirection
	 * @param accountId
	 *            l'identifiant du compte à afficher
	 * @param year
	 *            l'année à afficher
	 * @param month
	 *            le mois à afficher
	 * @param page
	 *            la page à afficher
	 * @return La vue card.jsp
	 */
	@RequestMapping("/{accountId}/card/{year}/{month}/{page}")
	public String cardTransactionsByAccountIdAndMonthAndPage(Model model,
			RedirectAttributes redirectAttributes,
			@PathVariable("accountId") int accountId,
			@PathVariable("year") int year, @PathVariable("month") int month,
			@PathVariable("page") int page) {

		Object[] params = { accountId, year, month, page };
		LOGGER.debug("/account/{}/card/{}/{}/{}", params);

		paginationController(model, accountId, year, month, page,
				TransactionType.CARD);

		model.addAttribute("dateSelectedMonth", getFirstDayOfMonth(year, month));

		return Template.page("accounts", "card", model,
				Account.class.cast(model.asMap().get("account")).getLabel());
	}
}
